#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>


class ThreadData
{
public:
    int Excute()
    {
        return x+y;
    }
public:
    std::string name;
    int x;
    int y;
};

 class ThreadResult
{
public:
    std::string print()
    {
        return std::to_string(x) + "+" + std::to_string(y) + "=" + std::to_string(result);
    }
public:
    int x;
    int y;
    int result;
};

std::string PrintToHex(pthread_t &tid)
{
    char buffer[64];
    snprintf(buffer,sizeof(buffer),"0x%lx",tid);
    return buffer;
}
//全面看待线程返回
//a.只考虑正确返回，如果异常了。整个进程会崩溃，包括主线程
//b.可以传递任意类型，甚至可以传递类对象地址
void* threadRun(void *args)
{
    //std::string name = (const char*)args;
    //int a = *(int*)args; // warning
    ThreadData *td = static_cast<ThreadData*>(args); // (ThreadData*)args
    ThreadResult *result = new ThreadResult();
    int cnt = 10;
    while(cnt)
    {
        sleep(3); 
        std::cout << td->name << " run ..." << ", cnt: " << cnt-- << std::endl;
        result->result = td->Excute();
        result->x = td->x;
        result->y = td->y;
        break;
        // int *p = nullptr;
        // *p = 100; // 故意野指针
    }
    delete td;
    return (void*)result;
}
void* threadrun(void* args)
{
 pthread_detach(pthread_self());
    std::string name = static_cast<const char*>(args);
    while(true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(3);
        // int *p = nullptr;
        // *p = 100;
        break;
    }
    // return args;
    // exit(1); // 进程: 专门用来终止进程的，不能用来终止线程！
    pthread_exit(args); // 专门终止一个线程的！
}
const int num=10;
int main()
{
    std::vector<pthread_t>tids;
    //怎么创建多线程
    for(int i=0;i<num;i++)
    {
        //1.创建线程要有线程id
        pthread_t tid;
        //2.线程名
        char *name = new char[128];
        snprintf(name, 128, "thread-%d", i+1);
        pthread_create(&tid, nullptr, threadrun, /*线程的名字*/name);
        //保存线程
        tids.push_back(tid);
    }
    //等待
    for(auto tid:tids)
    {
        pthread_detach(tid); // 主线程分离新线程，新线程必须存在
    }
    //线程怎么被终止？
    //1.线程return
    //2.phtrad_exit  如果是exit,则整个进程都会推出
    //3.main thrad call pthread.canncel,新线程退出结果是-1
    //线程可不可以不join，执行完直接退出呢？可以
    //a.一个线程如果被创建，默认是joinable,必须要被joion
    //b.如果一个线程被分离，线程的工作状态为分离太，不需要被join，依旧属于进程内部，但不需要被等待了
    pthread_t tid;
    ThreadData*td=new ThreadData();
    td->x=10;
    td->y=20;
    //int n=pthread_create(&tid,nullptr,threadRun,td);
    int n=pthread_create(&tid,nullptr,threadRun,(void*)&td);
    if(n != 0) // 后面我们暂时就关心了
    {
        std::cerr << "create thread error" << std::endl;
        return 1;
    }
    //打印tid 是虚拟地址
    std::string tid_str = PrintToHex(tid); // 我们按照16进行打印出来
    std::cout << "tid : " << tid_str << std::endl;
    //最后期望谁先退出呢？靠谁保证？：join
    ThreadResult* result=nullptr;
    n=pthread_join(tid,(void**)&result);//不join会造成类似僵尸进程的问题
    if(n==0)
    {
        std::cout << "main thread wait success, new thread exit code: " << result->print() << std::endl;
    }
    sleep(100);
    return 0;
}